package com.siemens.industrial.web.mvc.service;

import com.siemens.industrial.utils.ConfigurationUtil;
import com.siemens.industrial.utils.GlobalResponseCode;
import com.siemens.industrial.utils.SiemensException;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.fileupload.FileItem;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Iterator;
import java.util.List;

/**
 * Created by qupen on 2016/10/13.
 */
@Service
public class ImageService {
    public static String uploadImage(String name, List<FileItem> fileItems) throws SiemensException {
      /*  Iterator iterator = fileItems.iterator();*/
        FileItem item = fileItems.get(0);
        File tempFile = null;
        try {
            tempFile = File.createTempFile("image", "data");
            OutputStream os = new FileOutputStream(tempFile);
            os.write(item.get());
            os.flush();
            os.close();

            String md5Str = DigestUtils.md5Hex(new FileInputStream(tempFile));

            if (name == null || name.isEmpty())
                name = md5Str;

            if (!name.equals(md5Str))
                throw new SiemensException(GlobalResponseCode.ERROR_CREATE_FILE_FAILED);

            if (ConfigurationUtil.INSTANCE.getPreferredStorageEngine().toLowerCase().equals("local")) {
                return uploadImageToLocal(name, new FileInputStream(tempFile));
            }

            throw new SiemensException(GlobalResponseCode.ERROR_UNSUPPORTED_STORAGE_ENGINE);
        } catch (IOException e) {
            throw new SiemensException(GlobalResponseCode.ERROR_CREATE_FILE_FAILED);
        } finally {
            if (tempFile != null)
                tempFile.delete();
        }
    }

    private static String uploadImageToLocal(String name, InputStream body) throws SiemensException {
        File file = new File(getImagePath(name));

        if (file.exists())
            return name;

        try {
            FileOutputStream output = new FileOutputStream(file);

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = body.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
            }

            output.flush();
            output.close();

            return name;
        } catch (IOException e) {
            throw new SiemensException(GlobalResponseCode.ERROR_CREATE_FILE_FAILED);
        }
    }

    public static String getImagePath(String name) throws SiemensException {
        String fileName = String.format("%s%s", ConfigurationUtil.INSTANCE.getImagePath(), name.toLowerCase());
        File file = new File(fileName);

        if (!file.getParentFile().exists()) {
            if (!file.getParentFile().mkdirs()) {
                throw new SiemensException(GlobalResponseCode.ERROR_CREATE_DIR_FAILED);
            }
        }
        return fileName;
    }

    public static byte[] getImage(String name) throws SiemensException {
        assert name != null && !name.isEmpty();

        if (ConfigurationUtil.INSTANCE.getPreferredStorageEngine().toLowerCase().equals("local")) {
            return getImageFromLocal(name);
        }

        throw new SiemensException(GlobalResponseCode.ERROR_UNSUPPORTED_STORAGE_ENGINE);
    }

    private static byte[] getImageFromLocal(String name) throws SiemensException {
        String path = getImagePath(name);

        File file = new File(path);

        if (!file.exists())
            throw new SiemensException(GlobalResponseCode.ERROR_IMAGE_NOT_FOUND);

        InputStream in = null;

        try {
            in = new FileInputStream(file);
            return readInputStream(in);
        } catch (IOException e) {
            throw new SiemensException(GlobalResponseCode.ERROR_IMAGE_NOT_FOUND);
        } finally {
            try {
                in.close();
            } catch (IOException ignored) {

            }
        }
    }

    private static byte[] readInputStream(InputStream in) throws IOException {
        byte[] temp = new byte[in.available()];
        byte[] result = new byte[0];
        int size;
        while ((size = in.read(temp)) != -1) {
            byte[] readBytes = new byte[size];
            System.arraycopy(temp, 0, readBytes, 0, size);
            result = mergeArray(result, readBytes);
        }

        return result;
    }

    private static byte[] mergeArray(byte[]... a) {
        int index = 0;
        int sum = 0;
        for (int i = 0; i < a.length; i++) {
            sum = sum + a[i].length;
        }
        byte[] result = new byte[sum];
        for (int i = 0; i < a.length; i++) {
            int lengthOne = a[i].length;
            if (lengthOne == 0) {
                continue;
            }
            System.arraycopy(a[i], 0, result, index, lengthOne);
            index = index + lengthOne;
        }

        return result;
    }
}

